﻿package Chapter06;
// 將 StepIntoJava.java 內容替換為下列代碼即可運行
//======================================================================
//import Chapter06.SimpleBomb;
//
//public class StepIntoJava {
//	public static void main(String[] args) {
//		SimpleBomb game = new SimpleBomb();
//		game.run();
//	}	
//}
//======================================================================

import java.util.ArrayList;

public class SimpleBomb {
	// 存放地雷計算結果:周圍多少個地雷
	private ArrayList<Integer> cells = new ArrayList<Integer>();
	// 格子的編號，對應 cells 的 index
	private ArrayList<Integer> bombs = new ArrayList<Integer>();
	
	private int width;
	private int height;
	private int size;
	
	void setWidth(int value) {
		width = value;
		size = width * height;
	}
	void setHeight(int value) {
		height = value;
		size = width * height;
	}
	
//	public static void main(String[] args) {
//		Ch06SimpleBomb game = new Ch06SimpleBomb();
//		game.run();
//	}
	
	void run() {
		setupTable(10,4,9);// 寬、高、炸彈數
		printTable();
	}
	
	// 設定地雷位置與棋盤上的數字
	public void setupTable(int w, int h, int numOfBombs) {
		width = w;
		height = h;
		size = width*height;
		initial();
		randomBomb(numOfBombs);
		calculateAllCell();
	}

	// 初始化棋盤
	void initial() {
		cells.clear();
		for (int i = 0; i < size; i++) {
			cells.add(0);
		}
		bombs.clear();
	}
	
	// 計算出地雷的位置
	void randomBomb(int numOfBombs) {
		while(getBombs().size()<numOfBombs) {
			Integer bombIndex = (int)(Math.random()*size);
			if (!getBombs().contains(bombIndex)) {
				cells.set(bombIndex, -1);
				getBombs().add(bombIndex);
			}
		}
	}

	// 依照地雷位置取得每個格子的數值
	public void calculateAllCell() {
		for (int i =0; i < cells.size(); ++i) {
			Integer numOfNearBombs = cells.get(i);
			if (numOfNearBombs != -1) {
				cells.set(i, 0);
			}
		}		
		
		int rowSize = width;
		for (Integer bombIndex: getBombs()) {
			// 取得 bomb 所在行數
			int colIndex = bombIndex % rowSize;
			
			// 考慮左邊邊界情況，最左邊排不用計算左邊格子
			if (colIndex != 0) {
				cellPlusOne(bombIndex-1-rowSize); // 左上
				cellPlusOne(bombIndex-1);		  // 左邊
				cellPlusOne(bombIndex-1+rowSize); // 左下
			}
			// 考慮右邊邊界情況，最右邊排不用計算右邊格子
			if (colIndex != (rowSize-1)) {
				cellPlusOne(bombIndex+1-rowSize); // 右上
				cellPlusOne(bombIndex+1);		  // 右邊
				cellPlusOne(bombIndex+1+rowSize); // 右下
			}

			cellPlusOne(bombIndex-rowSize);
			cellPlusOne(bombIndex+rowSize);
		}
	}
	
	// 把 cellIndex 該格的地雷數字 + 1
	void cellPlusOne(int cellIndex) {
		if (cellIndex < 0 || cellIndex >=size) {
			return;
		}
		if (cells.get(cellIndex)==-1) {
			return;
		}
		cells.set(cellIndex, cells.get(cellIndex)+1);
	}
	
	// 畫出整個地雷棋盤
	public void printTable() {
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				Integer value = cells.get(i * width + j);
				String txt = (value == -1) ? "B" : value.toString();
				System.out.printf("[%s]", txt);
			}
			System.out.print("\n");	// 換行
		}
		System.out.println("--------------------");
	}
	
	// 取得 cellIndex 該格的周遭地雷數量
	public Integer getNumOfNearBombs(int cellIndex) {
		return cells.get(cellIndex);
	}
	
	// 檢查 cellIndex 該格是否有地雷
	public boolean isBombAt(Integer cellIndex) {
		return getBombs().contains(cellIndex);
	}
	
	// 移除 cellIndex 該格的地雷
	public void removeBombAt(Integer cellIndex) {
		cells.set(cellIndex, 0);
		getBombs().remove(cellIndex);
	}
	
	// 將 cellIndex 該格的地雷交換到從第一格開始最先找到的空白格
	public void swapBombAt(Integer cellIndex) {
		Integer toSwapIndex = 0;
		for (int i = 0; i < cells.size(); i++) {
			if (cells.get(i) != -1) {
				toSwapIndex = i;
				break;
			}
		}

		cells.set(cellIndex, 0);
		getBombs().remove(cellIndex);
		
		cells.set(toSwapIndex, -1);
		getBombs().add(toSwapIndex);
	}
	/**
	 * @return the bombs
	 */
	public ArrayList<Integer> getBombs() {
		return bombs;
	}
}
